package com.hxs.hxsserver.filter;

import com.alibaba.fastjson.JSON;
import com.hxs.hxsserver.exception.*;
import com.hxs.hxsserver.domain.dto.JsonResult;
import com.hxs.hxsserver.domain.dto.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


/**
 * 全局异常捕获
 *
 * @author Andi
 */
@Slf4j
@ControllerAdvice
public class GlobalErrorHandler {

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public JsonResult methodArgumentNotValidExceptionHandle(HttpServletRequest request, MethodArgumentNotValidException e) {
        log.warn("\nerror:thread:{}", Thread.currentThread().getName());
        log.warn("\nurl:{}\nmethod:{}\ne:{}", request.getRequestURI(), request.getMethod(), JSON.toJSONString(e));
        BindingResult result = e.getBindingResult();
        StringBuilder errorMsg = new StringBuilder();
        if (result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            fieldErrors.forEach(error -> {
                errorMsg.append(error.getDefaultMessage()).append("!");
            });
        }
        return JsonResult.builder().msg(errorMsg.toString()).code(ResponseCode.PARAM_ERROR_CODE.getCode()).build();
    }

    @ExceptionHandler({BindException.class})
    @ResponseBody
    public JsonResult bindExceptionHandle(HttpServletRequest request, BindException e) {
        log.warn("\nerror:thread:{}", Thread.currentThread().getName());
        log.warn("\nurl:{}\nmethod:{}\ne:{}", request.getRequestURI(), request.getMethod(), JSON.toJSONString(e));
        BindingResult result = e.getBindingResult();
        StringBuilder errorMsg = new StringBuilder();
        if (result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            fieldErrors.forEach(error -> {
                errorMsg.append(error.getDefaultMessage()).append("!");
            });
        }
        return JsonResult.builder().msg(errorMsg.toString()).code(ResponseCode.PARAM_ERROR_CODE.getCode()).build();
    }

    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public JsonResult businessExceptionHandle(HttpServletRequest request, BusinessException e) {
        log.warn("\nerror:thread:{},e:{}", Thread.currentThread().getName(), JSON.toJSONString(e));
        ResponseCode responseCode = ResponseCode.valueOf(e.getMessage());
        return JsonResult.builder().msg(responseCode.getDesc()).code(responseCode.getCode()).build();
    }

    @ExceptionHandler(ApiException.class)
    @ResponseBody
    public JsonResult apiExceptionHandle(HttpServletRequest request, ApiException e) {
        log.warn("\nerror:thread:{}", Thread.currentThread().getName());
        log.warn("\nurl:{}\nmethod:{}\ne:{}", request.getRequestURI(), request.getMethod(), JSON.toJSONString(e));
        return JsonResult.builder().msg(e.getMsg()).code(e.getCode()).build();
    }

    @ExceptionHandler(TokenException.class)
    @ResponseBody
    public JsonResult tokenExceptionHandle(HttpServletRequest request, TokenException e) {
        log.warn("\nerror:thread:{}", Thread.currentThread().getName());
        log.warn("\nurl:{}\nmethod:{}\ne:{}", request.getRequestURI(), request.getMethod(), JSON.toJSONString(e));
        return JsonResult.builder().msg("").code(ResponseCode.TOKEN_INVALID.getCode()).build();
    }

    @ExceptionHandler(TokenInvalidException.class)
    @ResponseBody
    public JsonResult tokenInvalidExceptionHandle(HttpServletResponse response, TokenInvalidException e) {
        return JsonResult.builder().msg("").code(ResponseCode.TOKEN_INVALID.getCode()).build();
    }

    @ExceptionHandler(LoginException.class)
    @ResponseBody
    public JsonResult loginExceptionHandle(HttpServletRequest request, LoginException e) {
        log.warn("\nerror:thread:{}", Thread.currentThread().getName());
        log.warn("\nurl:{}\nmethod:{}\ne:{}", request.getRequestURI(), request.getMethod(), JSON.toJSONString(e));
        return JsonResult.builder().msg(e.getMessage()).code(ResponseCode.FAILURE.getCode()).build();
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public JsonResult exceptionHandle(HttpServletRequest request, Exception e) {
        log.warn("\nerror:thread:{}", Thread.currentThread().getName());
        log.warn("\nurl:{}\nmethod:{}\ne:{}", request.getRequestURI(), request.getMethod(), e);
        return JsonResult.builder().msg("The system is busy, please try again later").code(ResponseCode.FAILURE.getCode()).build();
    }
}
